#ifndef _MATRIX_
#define _MATRIX_

#include <iostream>
#include <new>
#include <cstring>
using namespace std;

//template <typename T>
class Matrix{
 public:
  int row;
  int col;
  double *element;
  int setrow();
  int setcol();
  bool is_square();
  void alloc(int n);
  void release();
  Matrix operator*(Matrix& m1);
  double& operator()(int i, int j);
  void copy_data( double* _f, double* _t,int _d);
  Matrix& operator=(const Matrix& rhs);
  
  Matrix();
  ~Matrix();
};


void Matrix::copy_data( double* _f, double* _t,int _d){
  for (int i = 0; i < _d; i++)
    _t[i] = _f[i];
}

Matrix& Matrix::operator=(const Matrix& rhs){
  row = rhs.row;
  col = rhs.col;
  if(element != NULL)
    release();
  element = new double [row * col];
  for(int i = 0; i < row * col; i++)
    *(element + i) = *(rhs.element + i);
  return *this;
}

double& Matrix::operator()(int i, int j){
  //if(i < 0 || i > dimension -1 || j < 0 || j > dimension -1)
  return *(element + i * row + j);
}

void Matrix::alloc(int n){
  element = new double[n];
}

Matrix Matrix::operator*(Matrix& m1){
  Matrix result;
  result.row = row;
  result.col = m1.col;
  result.element = new double[ row * m1.col ];
  if( col != m1.row)
    return result;
  //initialize
  for(int i = 0; i < row; i++)
    for(int j  = 0; j < m1.col; j++)
      result(i,j) = 0;
  for(int i = 0; i < row; i++)
    for(int j  = 0; j < m1.col; j++)
      for(int k = 0; k < col; k++)
      	result( i , j ) = result( i, j ) + *(element + i * row + k) * m1( k, j);
  return result;
}

void Matrix::release(){
  if(element != NULL)
    delete [] element;
  element = NULL;
}

Matrix::Matrix(void){
  //cout <<"Obj is created!"<< endl;
  element = NULL;
}

int Matrix::setrow(void){
  cin >> row;
  return row;
}

int Matrix::setcol(void){
  cin >> col;
  return col;
}

Matrix::~Matrix(void){
  release();
  //cout <<"Obj is deleted!"<< endl;
}

bool Matrix::is_square(){
  alloc(row * col);
  if(row == col){
    dimension = row;
    return true;
  }else
    return false;
}

//vectorset

class vector:public Matrix{
 public:
  int setrowv();
  int setcolv();
  double operator*(vector& v1);

};

int vector::setrowv(){
  setcol();
  row = 1;
  return col;
}

int vector::setcolv(){
  setrow();
  col = 1;
  return row;
}

double vector::operator*(vector& v1){
  double result = 0;
  if( col != v1.row || row != v1.col){
    cout<< "ERROR! System will output 0!" <<endl;
    return 0;
  }
   
  for(int i = 0; i < col; i++)
    result = result + *(element + i) * v1(i,0);
  return result;
}



#else
//DO NOTHING
#endif
